package com.ruoyi.rpt.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.rpt.domain.RptCategory;
import com.ruoyi.rpt.domain.RptDefinition;
import com.ruoyi.rpt.mapper.RptCategoryMapper;
import com.ruoyi.rpt.service.IRptCategoryService;

/**
 * 报表分类Service业务层处理
 */
@Service
public class RptCategoryServiceImpl implements IRptCategoryService {
    
    @Autowired
    private RptCategoryMapper rptCategoryMapper;

    /**
     * 查询报表分类
     * 
     * @param categoryId 报表分类主键
     * @return 报表分类
     */
    @Override
    public RptCategory selectRptCategoryByCategoryId(Long categoryId) {
        return rptCategoryMapper.selectRptCategoryByCategoryId(categoryId);
    }

    /**
     * 查询报表分类列表
     * 
     * @param rptCategory 报表分类
     * @return 报表分类
     */
    @Override
    public List<RptCategory> selectRptCategoryList(RptCategory rptCategory) {
        return rptCategoryMapper.selectRptCategoryList(rptCategory);
    }
    
    /**
     * 构建前端所需要树结构
     * 
     * @param categories 分类列表
     * @return 树结构列表
     */
    @Override
    public List<RptCategory> buildCategoryTree(List<RptCategory> categories) {
        List<RptCategory> returnList = new ArrayList<>();
        List<Long> tempList = new ArrayList<>();
        
        for (RptCategory category : categories) {
            tempList.add(category.getCategoryId());
        }
        
        for (Iterator<RptCategory> iterator = categories.iterator(); iterator.hasNext();) {
            RptCategory category = iterator.next();
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(category.getParentId())) {
                recursionFn(categories, category);
                returnList.add(category);
            }
        }
        
        if (returnList.isEmpty()) {
            returnList = categories;
        }
        
        return returnList;
    }
    
    /**
     * 构建前端所需要下拉树结构
     * 
     * @param categories 分类列表
     * @return 下拉树结构列表
     */
    @Override
    public List<Map<String, Object>> buildCategoryTreeSelect(List<RptCategory> categories) {
        List<RptCategory> categoryTree = buildCategoryTree(categories);
        return categoryTree.stream().map(RptCategoryServiceImpl::categoryToMap).collect(Collectors.toList());
    }

    /**
     * 新增报表分类
     * 
     * @param rptCategory 报表分类
     * @return 结果
     */
    @Override
    public int insertRptCategory(RptCategory rptCategory) {
        rptCategory.setCreateTime(DateUtils.getNowDate());
        return rptCategoryMapper.insertRptCategory(rptCategory);
    }

    /**
     * 修改报表分类
     * 
     * @param rptCategory 报表分类
     * @return 结果
     */
    @Override
    public int updateRptCategory(RptCategory rptCategory) {
        rptCategory.setUpdateTime(DateUtils.getNowDate());
        return rptCategoryMapper.updateRptCategory(rptCategory);
    }

    /**
     * 批量删除报表分类
     * 
     * @param categoryIds 需要删除的报表分类主键
     * @return 结果
     */
    @Override
    public int deleteRptCategoryByCategoryIds(Long[] categoryIds) {
        for (Long categoryId : categoryIds) {
            // 检查是否有子分类
            List<RptCategory> childrenCategories = rptCategoryMapper.selectChildrenByParentId(categoryId);
            if (childrenCategories != null && !childrenCategories.isEmpty()) {
                throw new ServiceException(String.format("分类[%s]存在子分类,不能删除", categoryId));
            }
            
            // 检查分类下是否有报表
            List<RptDefinition> reports = rptCategoryMapper.selectReportsByCategory(categoryId);
            if (reports != null && !reports.isEmpty()) {
                throw new ServiceException(String.format("分类下存在报表,不能删除"));
            }
        }
        
        return rptCategoryMapper.deleteRptCategoryByCategoryIds(categoryIds);
    }

    /**
     * 删除报表分类信息
     * 
     * @param categoryId 报表分类主键
     * @return 结果
     */
    @Override
    public int deleteRptCategoryByCategoryId(Long categoryId) {
        // 检查是否有子分类
        List<RptCategory> childrenCategories = rptCategoryMapper.selectChildrenByParentId(categoryId);
        if (childrenCategories != null && !childrenCategories.isEmpty()) {
            throw new ServiceException(String.format("分类存在子分类,不能删除"));
        }
        
        // 检查分类下是否有报表
        List<RptDefinition> reports = rptCategoryMapper.selectReportsByCategory(categoryId);
        if (reports != null && !reports.isEmpty()) {
            throw new ServiceException(String.format("分类下存在报表,不能删除"));
        }
        
        return rptCategoryMapper.deleteRptCategoryByCategoryId(categoryId);
    }
    
    /**
     * 查询分类下的报表
     * 
     * @param categoryId 分类ID
     * @return 报表列表
     */
    @Override
    public List<RptDefinition> selectReportsByCategory(Long categoryId) {
        return rptCategoryMapper.selectReportsByCategory(categoryId);
    }
    
    /**
     * 关联报表到分类
     * 
     * @param reportId 报表ID
     * @param categoryIds 分类ID数组
     * @return 结果
     */
    @Override
    @Transactional
    public int relateReportToCategories(Long reportId, Long[] categoryIds) {
        // 先删除原有关联
        rptCategoryMapper.deleteReportCategoryByReportId(reportId);
        
        // 建立新关联
        int rows = 0;
        if (categoryIds != null && categoryIds.length > 0) {
            for (Long categoryId : categoryIds) {
                rows += rptCategoryMapper.insertReportCategory(reportId, categoryId);
            }
        }
        
        return rows;
    }
    
    /**
     * 递归列表
     */
    private void recursionFn(List<RptCategory> list, RptCategory t) {
        // 得到子节点列表
        List<RptCategory> childList = getChildList(list, t);
        t.setChildren(childList);
        for (RptCategory tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<RptCategory> getChildList(List<RptCategory> list, RptCategory t) {
        List<RptCategory> tlist = new ArrayList<>();
        for (RptCategory n : list) {
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().equals(t.getCategoryId())) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<RptCategory> list, RptCategory t) {
        return getChildList(list, t).size() > 0;
    }
    
    /**
     * 将分类对象转换成Map
     */
    private static Map<String, Object> categoryToMap(RptCategory category) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", category.getCategoryId());
        map.put("label", category.getCategoryName());
        
        List<RptCategory> children = category.getChildren();
        if (children != null && !children.isEmpty()) {
            map.put("children", children.stream().map(RptCategoryServiceImpl::categoryToMap).collect(Collectors.toList()));
        }
        
        return map;
    }
} 